#include "Image.h"

using namespace drawing;

namespace core {

	unsigned char ToChar( float val );
	float ToFloat( unsigned char val );

	Image::Image( unsigned int width, unsigned int height, ImagePixelFormat pixelFormat ) :
		m_width( width ),
		m_height( height ),
		m_pixelFormat( pixelFormat )
	{
		m_rawData = new unsigned char[ width * height * GetBytesPerPoint() ];
	}

	Image::~Image() {
		delete[] m_rawData;
	}

	unsigned char& Image::operator[]( unsigned int index ) {
		return m_rawData[index];
	}

	const unsigned char& Image::operator[]( unsigned int index ) const {
		return m_rawData[index];
	}

	Color Image::GetColor( unsigned int x, unsigned int y ) const {
		unsigned int base = GetIndex( x, y );

		switch( m_pixelFormat ) {
			case ImagePixelFormat::Rgba:
				return Color(
					ToFloat( m_rawData[base] ),
					ToFloat( m_rawData[base + 1] ),
					ToFloat( m_rawData[base + 2] ),
					ToFloat( m_rawData[base + 3] ) );
			case ImagePixelFormat::Rgb:
				return Color(
					ToFloat( m_rawData[base] ),
					ToFloat( m_rawData[base + 1] ),
					ToFloat( m_rawData[base + 2] ) );
			default:
				return Color(
					ToFloat( m_rawData[base] ),
					ToFloat( m_rawData[base + 1] ),
					ToFloat( m_rawData[base + 2] ),
					ToFloat( m_rawData[base + 3] ) );
		};
	}

	void Image::SetColor( const Color& color, unsigned int x, unsigned int y ) {
		unsigned int base = GetIndex( x, y );

		switch( m_pixelFormat ) {
			case ImagePixelFormat::Rgba:
				m_rawData[base] = ToChar( color.R );
				m_rawData[base + 1] = ToChar( color.G );
				m_rawData[base + 2] = ToChar( color.B );
				m_rawData[base + 3] = ToChar( color.A );
				break;
			case ImagePixelFormat::Rgb:
				m_rawData[base] = ToChar( color.R );
				m_rawData[base + 1] = ToChar( color.G );
				m_rawData[base + 2] = ToChar( color.B );
				break;
		};

	}

	unsigned int Image::GetIndex( unsigned int x, unsigned int y ) const {
		return ( y * m_width + x ) * GetBytesPerPoint();
	}

	unsigned char ToChar( float val ) {
		return (unsigned char)( val * 255.0f );
	}

	float ToFloat( unsigned char val ) {
		return float( val ) / 255.0f;
	}
}
